/* -*-c++-*- 
 * This source code is proprietary of ADIT
 * Copyright (C) 2013 Advanced Driver Information Technology Joint Venture GmbH
 * All rights reserved
 *
 * Author: Vadiraj Kaamsha <vadiraj.kaamsha@in.bosch.com>
 * Author: Rudolf Dederer <rudolf.dederer@de.bosch.com>
*/

#ifndef OSGBATCHEDTEXT_TEXTBATCHCONFIG
#define OSGBATCHEDTEXT_TEXTBATCHCONFIG 1

#include <osgText/Font>
#include <osgText/TextBase>
#include <osgBatchedText/BatchDrawableBase>
#include <osgBatchedText/Export>

namespace osgBatchedText {

class BatcherBase;

class OSGBATCHEDTEXT_EXPORT FontDescr
{
public:
   FontDescr() : _font(), _fontSize(0), _outlineSize(0) {}
   FontDescr(osgText::Font* font, unsigned int fontSize, unsigned int outlineSize)
      : _font(font), _fontSize(fontSize), _outlineSize(outlineSize) {}

   bool operator<(const FontDescr& rhs) const;
   bool operator==(const FontDescr& rhs) const;

   osg::ref_ptr<osgText::Font> _font;
   unsigned int _fontSize;
   unsigned int _outlineSize;
};

class OSGBATCHEDTEXT_EXPORT BatcherConfigBase : public osg::Referenced
{
public:
   BatcherConfigBase(BatchDrawableBase::tShaderType shaderType, int renderBin, int transpRenderBin = 0, float transpFactor = 0.0f, const osg::Vec3& originOffset = osg::Vec3());

   /** connect to BatcherBase drawable where the text would be drawn */
   void setBatcher(BatcherBase* batcherBase);
   BatcherBase* getBatcher() const;

   void setOriginOffset(const osg::Vec3& originOffset) { _originOffset = originOffset; }
   const osg::Vec3& getOriginOffset() const { return _originOffset; }

   void setShaderType(BatchDrawableBase::tShaderType shaderType);
   BatchDrawableBase::tShaderType getShaderType() const;
  
   void setRenderBin(int renderBin, int transpRenderBin = 0, float transpFactor = 0.0f);
   int getRenderBin() const { return _renderBin; }
   int getTranspRenderBin() const { return _transpRenderBin; }
   float getTranspFactor() const { return _transpFactor; }

   struct BatcherKeyComparator
   {
      bool operator()(const BatcherConfigBase* lhs, const BatcherConfigBase* rhs) const
      {
         return (lhs->_renderBin < rhs->_renderBin)
            || ((lhs->_renderBin == rhs->_renderBin) && ( (lhs->_batcherBase < rhs->_batcherBase)
                                                      || ((lhs->_batcherBase == rhs->_batcherBase) && (lhs->_shaderType < rhs->_shaderType))) );
      }
   };

protected:
   virtual ~BatcherConfigBase();

   /** pointer to BatcherBase which will draw this text */
   osg::ref_ptr<BatcherBase> _batcherBase;

   /** origin offset for local coordinates */
   osg::Vec3 _originOffset;

   /** render bin for opaque drawing */
   int _renderBin;

   /** render bin for transparent drawing */
   int _transpRenderBin;

   /** Transparency Factor: relative factor for alpha in transparent draw to normal draw */
   float _transpFactor;

   BatchDrawableBase::tShaderType _shaderType;
};


class OSGBATCHEDTEXT_EXPORT TextConfigBase : public BatcherConfigBase
{
public:
    TextConfigBase(unsigned int fontSize, unsigned int outlineSize, float charSize, bool has_outline, float lineSpacing,
                   osgText::TextBase::AlignmentType alignmentType, BatchDrawableBase::tShaderType shaderType, int renderBin, int transpRenderBin = 0, float transpFactor = 0.0f);

    const FontDescr& getFontDescr() const { return _fontDescr; }

    void setFont(osgText::Font* font) { _fontDescr._font = font; }
    osgText::Font* getFont() const { return _fontDescr._font.get(); }

    unsigned int getFontSize() const { return _fontDescr._fontSize; }

    unsigned int getOutlineSize() const { return _fontDescr._outlineSize; }

    float getLineSpacing() const { return _lineSpacing; }

    void setCharSize(float charSize) { _charSize = charSize; }
    float getCharSize() const { return _charSize; }

    void setColor(osg::Vec4& color) { _color = color;  }
    const osg::Vec4& getColor() const { return _color; }

    void setBackdropColor(osg::Vec4& backdropColor) { _backdropColor = backdropColor; }
    const osg::Vec4& getBackdropColor() const { return _backdropColor; }

    void setColors(osg::Vec4& color, osg::Vec4& backdropColor);

    osgText::TextBase::AlignmentType getAlignment() const { return _alignmentType; }

    bool isCurvedText() const;

    void setLayout(osgText::TextBase::Layout layout) { _layout = layout; }
    osgText::TextBase::Layout getLayout() const { return _layout; }

    bool hasOutline() const { return _has_outline; }

    virtual int getClassType() const { return 0; }

    inline bool operator < (const TextConfigBase& rhs) const;

protected:
    virtual ~TextConfigBase() {}

    FontDescr _fontDescr;

    /** sizes */
    float _charSize;
    float _lineSpacing;
    bool _has_outline;

    /** colors */
    osg::Vec4 _color;
    osg::Vec4 _backdropColor;

    osgText::TextBase::AlignmentType _alignmentType;

    osgText::TextBase::Layout _layout;
};

inline bool FontDescr::operator<(const FontDescr& rhs) const
{
   return (_font.get() < rhs._font.get())
      || ((_font.get() == rhs._font.get()) && ((_fontSize < rhs._fontSize) || ((_fontSize == rhs._fontSize) && (_outlineSize < rhs._outlineSize))));
}

inline bool FontDescr::operator==(const FontDescr& rhs) const
{
   return ((_font.get() == rhs._font.get()) && (_fontSize == rhs. _fontSize) && (_outlineSize == rhs._outlineSize));
}

inline void BatcherConfigBase::setRenderBin(int renderBin, int transpRenderBin, float transpFactor)
{
   _renderBin = renderBin;
   _transpRenderBin = transpRenderBin;
   _transpFactor = transpFactor;
}

inline bool TextConfigBase::operator<(const TextConfigBase& rhs) const
{
   return  (_fontDescr <  rhs._fontDescr)
       || ((_fontDescr == rhs._fontDescr) && ((_renderBin <  rhs._renderBin) || ((_renderBin == rhs._renderBin) && (_shaderType < rhs._shaderType))));
}

inline void TextConfigBase::setColors(osg::Vec4& color, osg::Vec4& backdropColor)
{
   _color = color;
   _backdropColor = backdropColor;
}

inline bool TextConfigBase::isCurvedText() const
{
   return BatchDrawableBase::isCurvedText(_shaderType);
}

inline void BatcherConfigBase::setShaderType(BatchDrawableBase::tShaderType shaderType)
{
   _shaderType = shaderType;
}

inline BatchDrawableBase::tShaderType BatcherConfigBase::getShaderType() const
{
   return _shaderType;
}


}

#endif